package com.yfqy.app.modules.wechat.util;

import lombok.extern.slf4j.Slf4j;

import java.security.MessageDigest;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;

@Slf4j
public class WechatPayJsApiUtil {

    /**
     * 生成小程序支付参数
     */
    public static Map<String, String> generateJsApiParams(String appId, String prepayId, String wxKey) {
        Map<String, String> params = new TreeMap<>();
        params.put("appId", appId);
        params.put("timeStamp", generateTimestamp());
        params.put("nonceStr", generateNonceStr());
        params.put("package", "prepay_id=" + prepayId);
        params.put("signType", "MD5");

        // 生成签名
        String sign = generateSign(params, wxKey);
        params.put("paySign", sign);

        return params;
    }

    /**
     * 生成随机字符串
     */
    private static String generateNonceStr() {
        return UUID.randomUUID().toString().replace("-", "").substring(0, 32);
    }

    /**
     * 生成时间戳
     */
    private static String generateTimestamp() {
        return String.valueOf(System.currentTimeMillis() / 1000);
    }

    /**
     * 生成MD5签名
     */
    private static String generateSign(Map<String, String> params, String key) {
        // 1. 参数名ASCII码从小到大排序
        TreeMap<String, String> sortedParams = new TreeMap<>(params);

        // 2. 拼接字符串
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
            if (entry.getValue() != null && !entry.getValue().isEmpty()) {
                sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
        }
        sb.append("key=").append(key);

        // 3. MD5加密并转大写
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(sb.toString().getBytes("UTF-8"));
            StringBuilder result = new StringBuilder();
            for (byte b : digest) {
                result.append(String.format("%02x", b));
            }
            return result.toString().toUpperCase();
        } catch (Exception e) {
            log.error("生成签名失败", e);
            return null;
        }
    }
}
